package org.jeecg.modules.pick.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Assert;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.aspect.annotation.AutoLog;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.constant.CommonConstant;
import org.jeecg.constant.WarehouseConstant;
import org.jeecg.modules.basic.basicSkuInfo.entity.BasicSkuInfo;
import org.jeecg.modules.basic.basicSkuInfo.service.IBasicSkuInfoService;
import org.jeecg.modules.in.entity.InOrderDetail;
import org.jeecg.modules.in.entity.InOrderInfo;
import org.jeecg.modules.in.service.IInOrderDetailService;
import org.jeecg.modules.in.service.IInOrderInfoService;
import org.jeecg.modules.inventory.inventoryInfo.entity.InventoryInfo;
import org.jeecg.modules.inventory.inventoryInfo.service.IInventoryInfoService;
import org.jeecg.modules.inventory.reportLabel.entity.ReportLabel;
import org.jeecg.modules.inventory.reportLabel.service.IReportLabelService;
import org.jeecg.modules.pick.entity.PickOrderDetail;
import org.jeecg.modules.pick.entity.PickOrderInfo;
import org.jeecg.modules.pick.service.IPickOrderDetailService;
import org.jeecg.modules.pick.service.IPickOrderInfoService;
import org.jeecg.modules.pick.vo.PickOrderInfoPage;
import org.jeecg.modules.system.util.QRCodeUtil;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
import org.jeecgframework.poi.excel.entity.ExportParams;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.jeecgframework.poi.excel.view.JeecgEntityExcelView;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.servlet.ModelAndView;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 理货管理
 * @Author: jeecg-boot
 * @Date: 2024-11-28
 * @Version: V1.0
 */
@Api(tags = "理货管理")
@RestController
@RequestMapping("/pick/pickOrderInfo")
@Slf4j
public class PickOrderInfoController {
    @Autowired
    private IPickOrderInfoService pickOrderInfoService;
    @Autowired
    private IPickOrderDetailService pickOrderDetailService;
    @Autowired
    private IBasicSkuInfoService basicSkuInfoService;
    @Autowired
    private IReportLabelService reportLabelService;
    @Autowired
    private IInventoryInfoService inventoryInfoService;
    @Autowired
    private IInOrderInfoService inOrderInfoService;
    @Autowired
    private IInOrderDetailService inOrderDetailService;

    /**
     * 分页列表查询
     *
     * @param pickOrderInfo
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "理货管理-网页分页列表查询")
    @ApiOperation(value = "理货管理-网页分页列表查询", notes = "理货管理-网页分页列表查询")
    @GetMapping(value = "/webList")
    public Result<?> queryPageListWeb(PickOrderInfo pickOrderInfo,
                                      @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                      @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                      HttpServletRequest req) {
        QueryWrapper<PickOrderInfo> queryWrapper = QueryGenerator.initQueryWrapper(pickOrderInfo, req.getParameterMap());
        queryWrapper.ne("status", WarehouseConstant.PickWarehouseStatusEnum.DELETE.getCode());
        Page<PickOrderInfo> page = new Page<PickOrderInfo>(pageNo, pageSize);
        IPage<PickOrderInfo> pageList = pickOrderInfoService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 分页列表查询
     *
     * @param pickOrderInfo
     * @param source        01：所有任务列表 02：过往任务列表
     * @param pageNo
     * @param pageSize
     * @param req
     * @return
     */
    @AutoLog(value = "理货管理-手持分页列表查询")
    @ApiOperation(value = "理货管理-手持分页列表查询", notes = "理货管理-手持分页列表查询")
    @GetMapping(value = "/appList")
    public Result<?> queryPageListApp(PickOrderInfo pickOrderInfo,
                                      @RequestParam(name = "source") String source,
                                      @RequestParam(name = "pageNo", defaultValue = "1") Integer pageNo,
                                      @RequestParam(name = "pageSize", defaultValue = "10") Integer pageSize,
                                      HttpServletRequest req) {
        QueryWrapper<PickOrderInfo> queryWrapper = QueryGenerator.initQueryWrapper(pickOrderInfo, req.getParameterMap());
        queryWrapper.ne("status", WarehouseConstant.PickWarehouseStatusEnum.DELETE.getCode());
        if (Objects.equals(source, "01")) {
            queryWrapper.eq("status", WarehouseConstant.PickWarehouseStatusEnum.RELEASE_END.getCode());
        } else if (Objects.equals(source, "02")) {
            LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
            queryWrapper.eq("execute_name", sysUser.getUsername());
            queryWrapper.ne("status", WarehouseConstant.PickWarehouseStatusEnum.DELETE.getCode());
        }
        Page<PickOrderInfo> page = new Page<>(pageNo, pageSize);
        IPage<PickOrderInfo> pageList = pickOrderInfoService.page(page, queryWrapper);
        return Result.OK(pageList);
    }

    /**
     * 生成货垛码
     *
     * @param
     * @return
     */
    @AutoLog(value = "理货管理-生成货垛码")
    @ApiOperation(value = "理货管理-生成货垛码", notes = "理货管理-生成货垛码")
    @PostMapping("/makeQRCode")
    public Result<?> makeQRCode(String stackCode) {
        String uniqueIdentification = UUID.randomUUID().toString().replace("-", "");
        String labelNumber = StringUtils.isBlank(stackCode) ? uniqueIdentification : stackCode + "-" + uniqueIdentification;

        BufferedImage bufferedImage = QRCodeUtil.produceLabel(labelNumber);
        String base64Str = "";
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            ImageIO.write(bufferedImage, "png", byteArrayOutputStream);
            byte[] imageBytes = byteArrayOutputStream.toByteArray();
            base64Str = Base64.getEncoder().encodeToString(imageBytes);
        } catch (Exception exception) {
            log.info("时间：{},bufferedImageToBase64方法出现异常：", LocalDateTime.now(), exception);
        }

        Map<String, String> returnMap = new HashMap<>();
        returnMap.put("labelNumber", StringUtils.isBlank(stackCode) ? uniqueIdentification.substring(0, 15) : stackCode);
        returnMap.put("base64Str", base64Str);
        return Result.OK(returnMap);
    }

    /**
     * 发布理货任务
     *
     * @param pickOrderId 理货单id
     * @return
     */
    @AutoLog(value = "理货管理-发布理货任务")
    @ApiOperation(value = "理货管理-发布理货任务", notes = "理货管理-发布理货任务")
    @PostMapping("/release")
    public Result<?> release(@RequestParam(name = "id") String pickOrderId) {
        PickOrderInfo pickOrderInfo = pickOrderInfoService.getById(pickOrderId);
        Assert.notNull(pickOrderInfo, "理货单数据异常，请联系管理员！");
        Assert.isFalse(Objects.equals(pickOrderInfo.getStatus(), WarehouseConstant.PickWarehouseStatusEnum.RELEASE_END.getCode()), "理货单已发布，请勿重复操作！");
        Assert.isFalse(Objects.equals(pickOrderInfo.getStatus(), WarehouseConstant.PickWarehouseStatusEnum.DELETE.getCode()), "理货单已被删除，无法发布！");
        Assert.isTrue(Objects.equals(pickOrderInfo.getStatus(), WarehouseConstant.PickWarehouseStatusEnum.CREATE_END.getCode()), "只有创建完成的理货单才可以发布！");

        List<PickOrderDetail> pickOrderDetailList = pickOrderDetailService.list(new LambdaQueryWrapper<PickOrderDetail>()
                .eq(PickOrderDetail::getPickOrderId, pickOrderId));
        Assert.notEmpty(pickOrderDetailList, "请填写理货单详情后发布！");

        Set<String> skuCodeSet = pickOrderDetailList.stream().map(PickOrderDetail::getSkuCode).collect(Collectors.toSet());
        for (String skuCode : skuCodeSet) {
            int skuCount = basicSkuInfoService.count(new LambdaQueryWrapper<BasicSkuInfo>()
                    .eq(BasicSkuInfo::getSkuCode, skuCode)
                    .eq(BasicSkuInfo::getSkuType, pickOrderInfo.getSkuType()));
            Assert.isTrue(skuCount > 0,
                    "【%s】中未维护品番编码【%s】，无法发布理货单！",
                    WarehouseConstant.SkuTypeEnum.getDefineByCode(pickOrderInfo.getSkuType()), skuCode);
        }

        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        pickOrderInfo.setReleaseName(sysUser.getUsername());
        pickOrderInfo.setReleaseTime(new Date());
        pickOrderInfo.setStatus(WarehouseConstant.PickWarehouseStatusEnum.RELEASE_END.getCode());
        pickOrderInfoService.updateById(pickOrderInfo);
        return Result.OK();
    }

    /**
     * 领取理货任务
     *
     * @param pickOrderId 理货单id
     * @return
     */
    @AutoLog(value = "理货管理-领取理货任务")
    @ApiOperation(value = "理货管理-领取理货任务", notes = "理货管理-领取理货任务")
    @PostMapping("/receive")
    public Result<?> receive(@RequestParam(name = "id") String pickOrderId) {
        PickOrderInfo pickOrderInfo = pickOrderInfoService.getById(pickOrderId);
        Assert.notNull(pickOrderInfo, "理货单数据异常，请联系管理员！");
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        int count = pickOrderInfoService.count(new LambdaQueryWrapper<PickOrderInfo>()
                .eq(PickOrderInfo::getExecuteName, sysUser.getUsername())
                .eq(PickOrderInfo::getStatus, WarehouseConstant.PickWarehouseStatusEnum.RECEIVE_END.getCode()));
        Assert.isTrue(count == 0, "您存在正在进行中的任务，无法重复领取任务！");

        pickOrderInfo.setExecuteName(sysUser.getUsername());
        pickOrderInfo.setExecuteTime(new Date());
        pickOrderInfo.setStatus(WarehouseConstant.PickWarehouseStatusEnum.RECEIVE_END.getCode());
        pickOrderInfoService.updateById(pickOrderInfo);
        return Result.OK();
    }

    /**
     * 扫码理货
     *
     * @param pickOrderDetail pickOrderId 前端传来的理货单id(需要和后端获取的当前登录人正在执行的理货单id相同，否则就是当前登录人执行了别的理货单)
     * @param pickOrderDetail labelNumber 扫描的货垛码对应的标签号
     * @return 理货单状态, 手持页面需要根据我返回的理货状态来判断是否展示发布任务的按钮
     */
    @AutoLog(value = "理货管理-扫码理货")
    @ApiOperation(value = "理货管理-扫码理货", notes = "理货管理-扫码理货")
    @PostMapping("/scanCode")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> scanCode(@RequestBody PickOrderDetail pickOrderDetail) {
        String pickOrderId = pickOrderDetail.getPickOrderId();
        String labelNumber = pickOrderDetail.getStackCode();
        Assert.isTrue(StringUtils.isNotBlank(pickOrderId), "缺少必要参数pickOrderId！");
        Assert.isTrue(StringUtils.isNotBlank(labelNumber), "缺少必要参数labelNumber！");
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 理货单
        PickOrderInfo pickOrderInfo = pickOrderInfoService.getOne(new LambdaQueryWrapper<PickOrderInfo>()
                .eq(PickOrderInfo::getExecuteName, sysUser.getUsername())
                .eq(PickOrderInfo::getStatus, WarehouseConstant.PickWarehouseStatusEnum.RECEIVE_END.getCode()));
        Assert.notNull(pickOrderInfo, "查询到您没有正在执行中的理货任务，无需扫码理货！");
        Assert.isTrue(Objects.equals(pickOrderInfo.getStatus(), WarehouseConstant.PickWarehouseStatusEnum.RECEIVE_END.getCode()),
                "理货单状态：【%s】，不支持拣货！", WarehouseConstant.PickWarehouseStatusEnum.getDefineByCode(pickOrderInfo.getStatus()));
        Assert.isTrue(Objects.equals(pickOrderId, pickOrderInfo.getId()), "请勿执行他人的理货任务！");
        // 理货单详情
        List<PickOrderDetail> list = pickOrderDetailService.list(new LambdaQueryWrapper<PickOrderDetail>()
                .eq(PickOrderDetail::getPickOrderId, pickOrderInfo.getId()));
        Assert.notEmpty(list, "后台数据中未查询到理货单对应的详情信息，请联系管理员！");
        // 货垛码
        String stackCode = null;
        for (PickOrderDetail orderDetail : list) {
            if (labelNumber.contains(orderDetail.getStackCode())) {
                stackCode = orderDetail.getStackCode();
            }
        }
        Assert.notNull(stackCode, "扫描的二维码不正确！");
        // 标签号重复校验
        int thisOrderStackCodeCount = reportLabelService.count(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                .eq(ReportLabel::getStackCode, stackCode)
                .eq(ReportLabel::getInOrderCode, pickOrderInfo.getPickOrderCode()));
        Assert.isTrue(thisOrderStackCodeCount == 0, "当前货垛已理货完成，请勿重复扫码！");
        int otherOrderLabelNumberCount = reportLabelService.count(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getLabelNumber, labelNumber)
                .ne(ReportLabel::getInOrderCode, pickOrderInfo.getPickOrderCode()));
        Assert.isTrue(otherOrderLabelNumberCount == 0, "查询后台数据中标签号已存在，无法使用，请重新生成货垛码使用！");


        // 过滤出扫码货垛的理货单详情，并按品番编码分组
        Map<String, List<PickOrderDetail>> map = list.stream()
                .filter(data -> labelNumber.contains(data.getStackCode()))
                .collect(Collectors.groupingBy(PickOrderDetail::getSkuCode));
        // 入库
        for (String skuCode : map.keySet()) {
            List<PickOrderDetail> pickOrderDetailList = map.get(skuCode);
            // 扫描的货垛中 这个品番的总箱数与总件数
            int boxQuantity = pickOrderDetailList.stream().mapToInt(PickOrderDetail::getBoxQuantity).sum();

            // report_label 理货区数据存储逻辑：以标签号、货垛码、品番编码与理货订单号作为唯一。
            ReportLabel reportLabel = new ReportLabel();
            reportLabel.setWarehouseCode(WarehouseConstant.WarehouseTypeEnum.PICK.getCode());
            reportLabel.setRoadCode(null); // 理货区没有货道编码
            reportLabel.setLabelNumber(labelNumber);
            reportLabel.setStackCode(stackCode);
            reportLabel.setSkuCode(skuCode);
            reportLabel.setInventoryBoxQuantity(boxQuantity);
            reportLabel.setAvailableBoxQuantity(boxQuantity);
            reportLabel.setSkuType(pickOrderInfo.getSkuType());
            reportLabel.setInOrderCode(pickOrderInfo.getPickOrderCode());
            reportLabel.setEnterDate(new Date());
            reportLabel.setStackingDate(new Date());
            reportLabel.setContainerNo(pickOrderInfo.getContainerNo());
            reportLabel.setOutOrderCode(null);
            reportLabelService.save(reportLabel);

            // inventory_info 理货区数据存储逻辑：以品番编码作为唯一(唯一条件不包含货垛码的原因是货垛码可能会重复)。
            InventoryInfo inventoryInfo = inventoryInfoService.getOne(new LambdaQueryWrapper<InventoryInfo>()
                    .eq(InventoryInfo::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                    .eq(InventoryInfo::getSkuCode, skuCode));
            if (null == inventoryInfo) {
                inventoryInfo = new InventoryInfo();
                inventoryInfo.setWarehouseCode(WarehouseConstant.WarehouseTypeEnum.PICK.getCode());
                inventoryInfo.setRoadCode(null); // 理货区没有货道编码
                inventoryInfo.setStackCode(null); // 理货区不存储货垛码，原因：可能会重复 数据不准
                inventoryInfo.setSkuCode(skuCode);
                inventoryInfo.setInventoryBoxQuantity(boxQuantity);
                inventoryInfo.setAvailableBoxQuantity(boxQuantity);
                inventoryInfo.setEnterDate(null); // 理货区不存储入库时间，原因：品番可能是分多批入进来的 数据不准
                inventoryInfo.setOutOrderCode(null);
                inventoryInfoService.save(inventoryInfo);
            } else {
                inventoryInfo.setInventoryBoxQuantity(inventoryInfo.getInventoryBoxQuantity() + boxQuantity);
                inventoryInfo.setAvailableBoxQuantity(inventoryInfo.getAvailableBoxQuantity() + boxQuantity);
                inventoryInfoService.updateById(inventoryInfo);
            }
        }

        // 校验理货是否完成
        Set<String> orderStackCodeSet = list.stream().map(PickOrderDetail::getStackCode).collect(Collectors.toSet());
        List<ReportLabel> reportLabelList = reportLabelService.list(new LambdaQueryWrapper<ReportLabel>()
                .eq(ReportLabel::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                .eq(ReportLabel::getInOrderCode, pickOrderInfo.getPickOrderCode()));
        Set<String> reportStackCodeSet = reportLabelList.stream().map(ReportLabel::getStackCode).collect(Collectors.toSet());
        if (reportStackCodeSet.equals(orderStackCodeSet)) {
            pickOrderInfo.setStatus(WarehouseConstant.PickWarehouseStatusEnum.EXECUTE_END.getCode());
            pickOrderInfo.setEndTime(new Date());
            pickOrderInfoService.updateById(pickOrderInfo);
        }

        return Result.OK(pickOrderInfo.getStatus());
    }

    /**
     * 发布任务
     *
     * @param pickOrderId 理货单id
     * @return
     */
    @AutoLog(value = "理货管理-发布任务")
    @ApiOperation(value = "理货管理-发布任务", notes = "理货管理-发布任务")
    @PostMapping("/releaseTask")
    @Transactional(rollbackFor = Exception.class)
    public Result<?> releaseTask(@RequestParam(name = "id") String pickOrderId) {
        PickOrderInfo pickOrderInfo = pickOrderInfoService.getById(pickOrderId);
        Assert.notNull(pickOrderInfo, "理货单数据异常，请联系管理员！");
        Assert.isTrue(pickOrderInfo.getStatus().equals(WarehouseConstant.PickWarehouseStatusEnum.EXECUTE_END.getCode()), "未拣货完成的理货单无法发布任务！");
        List<PickOrderDetail> list = pickOrderDetailService.list(new LambdaQueryWrapper<PickOrderDetail>().eq(PickOrderDetail::getPickOrderId, pickOrderId));
        Assert.notEmpty(list, "理货单详情数据异常，请联系管理员！");

        // inventory_info (更新可用库存)
        Map<String, List<PickOrderDetail>> map = list.stream().collect(Collectors.groupingBy(PickOrderDetail::getSkuCode));
        for (String skuCode : map.keySet()) {
            List<PickOrderDetail> pickOrderDetailList = map.get(skuCode);
            // 理货单内品番的总箱数与总件数
            int boxQuantity = pickOrderDetailList.stream().mapToInt(PickOrderDetail::getBoxQuantity).sum();
            // 库存信息
            InventoryInfo inventoryInfo = inventoryInfoService.getOne(new LambdaQueryWrapper<InventoryInfo>()
                    .eq(InventoryInfo::getWarehouseCode, WarehouseConstant.WarehouseTypeEnum.PICK.getCode())
                    .eq(InventoryInfo::getSkuCode, skuCode));
            Assert.notNull(inventoryInfo, "库存数据异常，请联系管理员！");
            Assert.isTrue(boxQuantity <= inventoryInfo.getAvailableBoxQuantity(),
                    "当前理货单中，品番编码【%s】共计【%s】箱，理货区内可用库存【%s】箱，理货区库存不足，无法发布入库任务！", skuCode, boxQuantity, inventoryInfo.getAvailableBoxQuantity());

            inventoryInfo.setAvailableBoxQuantity(inventoryInfo.getAvailableBoxQuantity() - boxQuantity);
            inventoryInfoService.updateById(inventoryInfo);
        }


        // 创建入库单
        InOrderInfo inOrder = new InOrderInfo();
        inOrder.setInOrderCode(pickOrderInfo.getPickOrderCode());
        inOrder.setContainerNo(pickOrderInfo.getContainerNo());
        inOrder.setInOrderTime(new Date());
        inOrder.setSkuType(pickOrderInfo.getSkuType());
        inOrder.setRemarks(pickOrderInfo.getRemarks());
        inOrder.setStatus(WarehouseConstant.EnterWarehouseStatusEnum.CREATE_END.getCode());
        inOrderInfoService.save(inOrder);
        // 创建入库单详情
        List<InOrderDetail> inOrderDetailList = new ArrayList<>();
        for (PickOrderDetail pickOrderDetail : list) {
            InOrderDetail inOrderDetail = new InOrderDetail();
            inOrderDetail.setInOrderId(inOrder.getId());
            inOrderDetail.setStackCode(pickOrderDetail.getStackCode());
            inOrderDetail.setSkuCode(pickOrderDetail.getSkuCode());
            inOrderDetail.setBoxQuantity(pickOrderDetail.getBoxQuantity());
            inOrderDetail.setStatus(CommonConstant.StatusEnum.YES.getCode());
            inOrderDetailList.add(inOrderDetail);
        }
        inOrderDetailService.saveBatch(inOrderDetailList);

        // 发布入库单
        inOrderInfoService.releaseWarehousingEntry(inOrder.getId());

        // 更新理货状态
        pickOrderInfo.setStatus(WarehouseConstant.PickWarehouseStatusEnum.ENTER_ORDER.getCode());
        pickOrderInfoService.updateById(pickOrderInfo);

        return Result.OK();
    }

    /**
     * 添加
     *
     * @param pickOrderInfoPage
     * @return
     */
    @AutoLog(value = "理货管理-添加")
    @ApiOperation(value = "理货管理-添加", notes = "理货管理-添加")
    @PostMapping(value = "/add")
    public Result<?> add(@RequestBody PickOrderInfoPage pickOrderInfoPage) {
        PickOrderInfo pickOrderInfo = new PickOrderInfo();
        BeanUtils.copyProperties(pickOrderInfoPage, pickOrderInfo);
        pickOrderInfoService.savePickOrder(pickOrderInfo, pickOrderInfoPage.getPickOrderDetailList());
        return Result.OK("添加成功！");
    }

    /**
     * 编辑
     *
     * @param pickOrderInfoPage
     * @return
     */
    @AutoLog(value = "理货管理-编辑")
    @ApiOperation(value = "理货管理-编辑", notes = "理货管理-编辑")
    @PutMapping(value = "/edit")
    public Result<?> edit(@RequestBody PickOrderInfoPage pickOrderInfoPage) {
        PickOrderInfo pickOrderInfo = new PickOrderInfo();
        BeanUtils.copyProperties(pickOrderInfoPage, pickOrderInfo);
        PickOrderInfo pickOrderInfoEntity = pickOrderInfoService.getById(pickOrderInfo.getId());
        if (pickOrderInfoEntity == null) {
            return Result.error("未找到对应数据");
        }
        pickOrderInfoService.savePickOrder(pickOrderInfo, pickOrderInfoPage.getPickOrderDetailList());
        return Result.OK("编辑成功!");
    }

    /**
     * 通过id删除
     *
     * @param id
     * @return
     */
    @AutoLog(value = "理货管理-通过id删除")
    @ApiOperation(value = "理货管理-通过id删除", notes = "理货管理-通过id删除")
    @DeleteMapping(value = "/delete")
    public Result<?> delete(@RequestParam(name = "id", required = true) String id) {
        pickOrderInfoService.delMain(id);
        return Result.OK("删除成功!");
    }

    /**
     * 批量删除
     *
     * @param ids
     * @return
     */
    @AutoLog(value = "理货管理-批量删除")
    @ApiOperation(value = "理货管理-批量删除", notes = "理货管理-批量删除")
    @DeleteMapping(value = "/deleteBatch")
    public Result<?> deleteBatch(@RequestParam(name = "ids", required = true) String ids) {
        this.pickOrderInfoService.delBatchMain(Arrays.asList(ids.split(",")));
        return Result.OK("批量删除成功！");
    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "理货管理-通过id查询")
    @ApiOperation(value = "理货管理-通过id查询", notes = "理货管理-通过id查询")
    @GetMapping(value = "/queryById")
    public Result<?> queryById(@RequestParam(name = "id", required = true) String id) {
        PickOrderInfo pickOrderInfo = pickOrderInfoService.getById(id);
        if (pickOrderInfo == null) {
            return Result.error("未找到对应数据");
        }
        return Result.OK(pickOrderInfo);

    }

    /**
     * 通过id查询
     *
     * @param id
     * @return
     */
    @AutoLog(value = "理货单详情通过主表ID查询")
    @ApiOperation(value = "理货单详情主表ID查询", notes = "理货单详情-通主表ID查询")
    @GetMapping(value = "/queryPickOrderDetailByMainId")
    public Result<?> queryPickOrderDetailListByMainId(@RequestParam(name = "id", required = true) String id) {
        List<PickOrderDetail> pickOrderDetailList = pickOrderDetailService.selectByMainId(id);
        return Result.OK(pickOrderDetailList);
    }

    /**
     * 导出excel
     *
     * @param request
     * @param pickOrderInfo
     */
    @RequestMapping(value = "/exportXls")
    public ModelAndView exportXls(HttpServletRequest request, PickOrderInfo pickOrderInfo) {
        // Step.1 组装查询条件查询数据
        QueryWrapper<PickOrderInfo> queryWrapper = QueryGenerator.initQueryWrapper(pickOrderInfo, request.getParameterMap());
        queryWrapper.ne("status", WarehouseConstant.PickWarehouseStatusEnum.DELETE.getCode());
        LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();

        //Step.2 获取导出数据
        List<PickOrderInfo> queryList = pickOrderInfoService.list(queryWrapper);
        // 过滤选中数据
        String selections = request.getParameter("selections");
        List<PickOrderInfo> pickOrderInfoList = new ArrayList<PickOrderInfo>();
        if (oConvertUtils.isEmpty(selections)) {
            pickOrderInfoList = queryList;
        } else {
            List<String> selectionList = Arrays.asList(selections.split(","));
            pickOrderInfoList = queryList.stream().filter(item -> selectionList.contains(item.getId())).collect(Collectors.toList());
        }

        // Step.3 组装pageList
        List<PickOrderInfoPage> pageList = new ArrayList<PickOrderInfoPage>();
        for (PickOrderInfo main : pickOrderInfoList) {
            PickOrderInfoPage vo = new PickOrderInfoPage();
            BeanUtils.copyProperties(main, vo);
            List<PickOrderDetail> pickOrderDetailList = pickOrderDetailService.selectByMainId(main.getId());
            vo.setPickOrderDetailList(pickOrderDetailList);
            pageList.add(vo);
        }

        // Step.4 AutoPoi 导出Excel
        ModelAndView mv = new ModelAndView(new JeecgEntityExcelView());
        mv.addObject(NormalExcelConstants.FILE_NAME, "理货管理列表");
        mv.addObject(NormalExcelConstants.CLASS, PickOrderInfoPage.class);
        mv.addObject(NormalExcelConstants.PARAMS, new ExportParams("理货管理数据", "导出人:" + sysUser.getRealname(), "理货管理"));
        mv.addObject(NormalExcelConstants.DATA_LIST, pageList);
        return mv;
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/importExcel", method = RequestMethod.POST)
    public Result<?> importExcel(HttpServletRequest request, HttpServletResponse response) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            MultipartFile file = entity.getValue();// 获取上传文件对象
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<PickOrderInfoPage> list = ExcelImportUtil.importExcel(file.getInputStream(), PickOrderInfoPage.class, params);
                for (PickOrderInfoPage page : list) {
                    PickOrderInfo po = new PickOrderInfo();
                    BeanUtils.copyProperties(page, po);
                    pickOrderInfoService.savePickOrder(po, page.getPickOrderDetailList().stream().filter(data -> StringUtils.isNotBlank(data.getStackCode()) && StringUtils.isNotBlank(data.getSkuCode())).collect(Collectors.toList()));
                }
                return Result.OK("文件导入成功！数据行数:" + list.size());
            } catch (Exception e) {
                log.error(e.getMessage(), e);
                return Result.error("文件导入失败:" + e.getMessage());
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.OK("文件导入失败！");
    }

}
